package jp.dodododo.aop.interceptors;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Map;

import jp.dodododo.aop.annotation.Enhance;

import org.aopalliance.intercept.ConstructorInvocation;
import org.aopalliance.intercept.MethodInvocation;

/**
 * {@.en }
 * 
 * <br />
 * 
 * {@.ja Mock用のInterceptorです。}
 * 
 * @author Satoshi Kimura
 */
@Enhance(false)
public class MockInterceptor implements ConstructorInterceptor, MethodInterceptor {

	private Map<String, Object> returnValueMap = new HashMap<String, Object>();

	private Map<String, Throwable> throwableMap = new HashMap<String, Throwable>();

	public static MockInterceptor getInstance() {
		return new MockInterceptor();
	}

	public Object construct(ConstructorInvocation invocation) throws Throwable {
		return null;
	}

	public Object invoke(MethodInvocation invocation) throws Throwable {
		Method method = invocation.getMethod();
		boolean isAbstract = Modifier.isAbstract(method.getModifiers());
		String methodName = method.getName();
		if (throwableMap.containsKey(methodName)) {
			throw throwableMap.get(methodName);
		} else if (throwableMap.containsKey(null)) {
			throw throwableMap.get(null);
		} else if (returnValueMap.containsKey(methodName)) {
			return returnValueMap.get(methodName);
		} else if (returnValueMap.containsKey(null)) {
			return returnValueMap.get(null);
		} else if (isAbstract == true) {
			return returnValueMap.get(null);
		} else {
			return invocation.proceed();
		}
	}

	public MockInterceptor setReturnValue(Object returnValue) {
		return setReturnValue(null, returnValue);
	}

	public MockInterceptor setReturnValue(String methodName, Object returnValue) {
		returnValueMap.put(methodName, returnValue);
		return this;
	}

	public MockInterceptor setThrowable(String methodName, Throwable throwable) {
		throwableMap.put(methodName, throwable);
		return this;
	}

	public MockInterceptor setThrowable(Throwable throwable) {
		return setThrowable(null, throwable);
	}
}
